package org.wbd.pklib.db.logic;

import java.sql.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.hibernate.*;
import org.wbd.pklib.db.Book;
import org.wbd.pklib.db.DataBaseSession;
import org.wbd.pklib.db.Item;
import org.wbd.pklib.db.ItemJoin;
import org.wbd.pklib.db.Loan;
import org.wbd.pklib.db.Repo;
import org.wbd.pklib.db.RepoUser;
import org.wbd.pklib.db.User;

/**
 * Singleton obsługujący operacje na bazie danych zwiazne z wypozyczeniami
 */
public class LoanLogic {
	private SessionFactory sessionFactory;
	static private LoanLogic loanLogic = null;

	private LoanLogic() {
		sessionFactory = DataBaseSession.getInstance().getSessionFactory();

	};

	/**
	 * Zwraca instancje LoanLogic
	 */
	static public LoanLogic getInstance() {
		if (loanLogic == null) {
			loanLogic = new LoanLogic();
		}
		return loanLogic;
	}

	/**
	 * Pozwala wypozyczyc dany egzemplarz ksiazki (item) przez uzytkownika (user)
	 */
	public LogicRespond LoanBook(User user, Item item) {

		java.util.Calendar cal = java.util.Calendar.getInstance();
		java.util.Date utilDate = cal.getTime();
		java.sql.Date sqlDate = new Date(utilDate.getTime());

		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			Loan newLoan = new Loan(null, user.getUserId(), item.getItemId(),
					sqlDate, null, null);

			
			List<Object> result = session.createQuery("from Loan where itemId = " + item.getItemId()+ " and returnDate is null").list() ;
			if (result.size() != 0){
				return new LogicRespond("Book unavailable ", false);
			}
			
			session.save(newLoan);

			session.getTransaction().commit();
			session.close();
			return new LogicRespond("Loan", true);
		} catch (Exception e) {
			return new LogicRespond("DB error", false);
		}
	}

	/**
	 * Pozwala wypozyczyc  egzemplarz ksiazki o podanym id przez uzytkownika (user)
	 */
	public LogicRespond LoanBook(User user, Integer itemId) {

		java.util.Calendar cal = java.util.Calendar.getInstance();
		java.util.Date utilDate = cal.getTime();
		java.sql.Date sqlDate = new Date(utilDate.getTime());

		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			Loan newLoan = new Loan(null, user.getUserId(), itemId, sqlDate,
					null, null);
			session.save(newLoan);

			session.getTransaction().commit();
			session.close();
			return new LogicRespond("Wypożyczono książke", true);
		} catch (Exception e) {
			return new LogicRespond("DB error", false);
		}
	}

	/**
	 * Zwraca ksiazke i pozwala dodac opinie na jej temat
	 */
	public LogicRespond returnBook(Loan loan, String opinion) {

		java.util.Calendar cal = java.util.Calendar.getInstance();
		java.util.Date utilDate = cal.getTime();
		java.sql.Date sqlDate = new Date(utilDate.getTime());

		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			loan.setReturnDate(sqlDate);
			loan.setOpinion(opinion);

			session.update(loan);
			session.getTransaction().commit();
			session.close();
			return new LogicRespond("Książka została oddana", true);
		} catch (Exception e) {
			return new LogicRespond("DB error", false);
		}
	}

	/**
	 * Zwraca liste wypozyczen danego uzytkownika
	 */
	public LogicRespond getUserLoans(User user) {

		LogicRespond logicRespond;
		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			List<Object> result = session.createQuery(
					"from Loan where userId = " + user.getUserId()).list();
			logicRespond = new LogicRespond("Loans List", true);
			logicRespond.setResultList(result);

			session.getTransaction().commit();
			session.close();
		} catch (Exception e) {
			logicRespond = new LogicRespond("DB error", false);
		}
		return logicRespond;
	}

	public LogicRespond getLoanByItem(Item item) {
		LogicRespond logicRespond;
		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			List<Object> result = session.createQuery("from Loan where itemId= "
					+ item.getItemId()+"and returnDate is null").list();
			logicRespond = new LogicRespond("Lent book", true);
			logicRespond.setResultObject(result.get(0));

			session.getTransaction().commit();
			session.close();
		} catch (Exception e) {
			logicRespond = new LogicRespond("DB error", false);
		}
		return logicRespond;
	}

	/**
	 * Zwraca niezakonczone wypozyczenia danego uzytkownika
	 */
	public LogicRespond getUnfinishedUserLoans(User user) {

		LogicRespond logicRespond;
		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			List<Object> result = session.createQuery(
					"from Loan where userId = " + user.getUserId()
							+ "and returnDate is  null").list();
			logicRespond = new LogicRespond("Unfinished Loans List", true);
			logicRespond.setResultList(result);

			session.getTransaction().commit();
			session.close();
		} catch (Exception e) {
			logicRespond = new LogicRespond("DB error", false);
		}
		return logicRespond;
	}

	/**
	 * Zwraca zakonczone wypozyczenia danego uzytkownika
	 */
	public LogicRespond getFinishedUserLoans(User user) {

		LogicRespond logicRespond;
		try {
			Session session = sessionFactory.openSession();
			session.beginTransaction();

			List<Object> result = session.createQuery(
					"from Loan where userId = " + user.getUserId()
							+ "and returnDate is not null").list();
			logicRespond = new LogicRespond("Finished Loans List", true);
			logicRespond.setResultList(result);

			session.getTransaction().commit();
			session.close();
		} catch (Exception e) {
			logicRespond = new LogicRespond("DB error", false);
		}
		return logicRespond;
	}

}